


#ifndef _MP_MATHPLOT_H_
#define _MP_MATHPLOT_H_





#ifdef mathplot_EXPORTS 
 #define WXDLLIMPEXP_MATHPLOT WXEXPORT 
 #define WXDLLIMPEXP_DATA_MATHPLOT(type) WXEXPORT type 
#else // not making DLL 
 #define WXDLLIMPEXP_MATHPLOT 
 #define WXDLLIMPEXP_DATA_MATHPLOT(type) type 
#endif

#if defined(__GNUG__) && !defined(__APPLE__)
#pragma interface "mathplot.h"
#endif

#include <vector>

#include <wx/defs.h>
#include <wx/menu.h>
#include <wx/scrolwin.h>
#include <wx/event.h>
#include <wx/dynarray.h>
#include <wx/pen.h>
#include <wx/dcmemory.h>
#include <wx/string.h>
#include <wx/print.h>
#include <wx/image.h>


#include <deque>

#ifdef _WINDOWS
#ifdef _DEBUG
#include <crtdbg.h>
#define DEBUG_NEW new(_NORMAL_BLOCK ,__FILE__, __LINE__)
#else
#define DEBUG_NEW new
#endif #endif 
#define X_BORDER_SEPARATION 40
#define Y_BORDER_SEPARATION 60



class WXDLLIMPEXP_MATHPLOT mpLayer;
class WXDLLIMPEXP_MATHPLOT mpFX;
class WXDLLIMPEXP_MATHPLOT mpFY;
class WXDLLIMPEXP_MATHPLOT mpFXY;
class WXDLLIMPEXP_MATHPLOT mpFXYVector;
class WXDLLIMPEXP_MATHPLOT mpScaleX;
class WXDLLIMPEXP_MATHPLOT mpScaleY;
class WXDLLIMPEXP_MATHPLOT mpWindow;
class WXDLLIMPEXP_MATHPLOT mpText;
class WXDLLIMPEXP_MATHPLOT mpPrintout;


enum
{
    mpID_FIT = 2000,    //!< Fit view to match bounding box of all layers
    mpID_ZOOM_IN,       //!< Zoom into view at clickposition / window center
    mpID_ZOOM_OUT,      //!< Zoom out
    mpID_CENTER,        //!< Center view on click position
    mpID_LOCKASPECT,    //!< Lock x/y scaling aspect
    mpID_HELP_MOUSE     //!< Shows information about the mouse commands
};



typedef enum __mp_Layer_Type {
    mpLAYER_UNDEF,  //!< Layer type undefined
    mpLAYER_AXIS,  //!< Axis type layer
    mpLAYER_PLOT,  //!< Plot type layer
    mpLAYER_INFO,   //!< Info box type layer
    mpLAYER_BITMAP //!< Bitmap type layer
} mpLayerType;


class WXDLLIMPEXP_MATHPLOT mpLayer : public wxObject
{
public:
    mpLayer();

    virtual ~mpLayer() {};

    
    virtual bool   HasBBox() { return TRUE; }

    
    virtual bool IsInfo() { return false; };

    
    virtual double GetMinX() { return -1.0; }

    
    virtual double GetMaxX() { return  1.0; }

    
    virtual double GetMinY() { return -1.0; }

    
    virtual double GetMaxY() { return  1.0; }

    
    virtual void   Plot(wxDC & dc, mpWindow & w) = 0;

    
    wxString       GetName() const { return m_name; }

    
    const wxFont&  GetFont() const { return m_font; }

    
    const wxPen&   GetPen()  const { return m_pen;  }

    
    void SetContinuity(bool continuity) {m_continuous = continuity;}

    
    bool GetContinuity() const {return m_continuous;}

    
    void ShowName(bool show) { m_showName = show; };

    
    void SetName(wxString name) { m_name = name; }

    
    void SetFont(wxFont& font)  { m_font = font; }

    
    void SetPen(wxPen pen)     { m_pen  = pen;  }

    
    void SetDrawOutsideMargins(bool drawModeOutside) { m_drawOutsideMargins = drawModeOutside; };

    
    bool GetDrawOutsideMargins() { return m_drawOutsideMargins; };

    
    wxBitmap GetColourSquare(int side = 16);

    
    mpLayerType GetLayerType() { return m_type; };
	
    
    bool IsVisible() {return m_visible; };

    
    void SetVisible(bool show) { m_visible = show; };
	
	
	const wxBrush&   GetBrush() const { return m_brush; };
	
	
	void SetBrush(wxBrush brush) { m_brush = brush; };

protected:
    wxFont   m_font;    //!< Layer's font
    wxPen    m_pen;     //!< Layer's pen
	wxBrush  m_brush;       //!< Layer's brush
    wxString m_name;    //!< Layer's name
    bool     m_continuous; //!< Specify if the layer will be plotted as a continuous line or a set of points.
    bool     m_showName;  //!< States whether the name of the layer must be shown (default is true).
    bool     m_drawOutsideMargins; //!< select if the layer should draw only inside margins or over all DC
    mpLayerType m_type; //!< Define layer type, which is assigned by constructor
	bool 	m_visible;
    DECLARE_DYNAMIC_CLASS(mpLayer)
};





class WXDLLIMPEXP_MATHPLOT mpInfoLayer : public mpLayer
{
public:
    
    mpInfoLayer();

    
    mpInfoLayer(wxRect rect, const wxBrush* brush = wxTRANSPARENT_BRUSH);

    
    virtual ~mpInfoLayer();

    
    virtual void UpdateInfo(mpWindow& w, wxEvent& event);

    
    virtual bool HasBBox() { return false; };

    
    virtual void   Plot(wxDC & dc, mpWindow & w);

    
    virtual bool IsInfo() { return true; };

    
    virtual bool Inside(wxPoint& point);

    
    virtual void Move(wxPoint delta);

    
    virtual void UpdateReference();

    
    wxPoint GetPosition();

    
    wxSize GetSize();
	
	
	const wxRect& GetRectangle() { return m_dim; };

protected:
    wxRect m_dim;           //!< The bounding rectangle of the box. It may be resized dynamically by the Plot method.
    wxPoint m_reference;    //!< Holds the reference point for movements
    wxBrush m_brush;        //!< The brush to be used for the background
    int m_winX, m_winY;     //!< Holds the mpWindow size. Used to rescale position when window is resized.
    
    DECLARE_DYNAMIC_CLASS(mpInfoLayer)
};


class WXDLLIMPEXP_MATHPLOT mpInfoCoords : public mpInfoLayer
{
public:
    
    mpInfoCoords();
    
    mpInfoCoords(wxRect rect, const wxBrush* brush = wxTRANSPARENT_BRUSH);

    
    ~mpInfoCoords();

    
    virtual void UpdateInfo(mpWindow& w, wxEvent& event);

    
    virtual void   Plot(wxDC & dc, mpWindow & w);

protected:
    wxString m_content; //!< string holding the coordinates to be drawn.
};


class WXDLLIMPEXP_MATHPLOT mpInfoLegend : public mpInfoLayer
{
public:
    
    mpInfoLegend();

    
    mpInfoLegend(wxRect rect, const wxBrush* brush = wxTRANSPARENT_BRUSH);

    
    ~mpInfoLegend();

    
    virtual void UpdateInfo(mpWindow& w, wxEvent& event);

    
    virtual void   Plot(wxDC & dc, mpWindow & w);

protected:
    
};







#define mpALIGNMASK    0x03

#define mpALIGN_RIGHT  0x00

#define mpALIGN_CENTER 0x01

#define mpALIGN_LEFT   0x02

#define mpALIGN_TOP    mpALIGN_RIGHT

#define mpALIGN_BOTTOM mpALIGN_LEFT

#define mpALIGN_BORDER_BOTTOM  0x04

#define mpALIGN_BORDER_TOP  0x05

#define mpX_NORMAL  0x00

#define mpX_TIME  0x01

#define mpX_HOURS 0x02

#define mpX_DATE 0x03

#define mpX_DATETIME 0x04

#define mpALIGN_BORDER_LEFT mpALIGN_BORDER_BOTTOM

#define mpALIGN_BORDER_RIGHT mpALIGN_BORDER_TOP

#define mpALIGN_NE     0x00

#define mpALIGN_NW     0x01

#define mpALIGN_SW     0x02

#define mpALIGN_SE     0x03






class WXDLLIMPEXP_MATHPLOT mpFX : public mpLayer
{
public:
    
    mpFX(wxString name = wxEmptyString, int flags = mpALIGN_RIGHT);

    
    virtual double GetY( double x ) = 0;

    
    virtual void Plot(wxDC & dc, mpWindow & w);

protected:
    int m_flags; 
    DECLARE_DYNAMIC_CLASS(mpFX)
};


class WXDLLIMPEXP_MATHPLOT mpFY : public mpLayer
{
public:
    
    mpFY(wxString name = wxEmptyString, int flags = mpALIGN_TOP);

    
    virtual double GetX( double y ) = 0;

    
    virtual void Plot(wxDC & dc, mpWindow & w);

protected:
    int m_flags; 
    DECLARE_DYNAMIC_CLASS(mpFY)
};


class WXDLLIMPEXP_MATHPLOT mpFXY : public mpLayer
{
public:
    
    mpFXY(wxString name = wxEmptyString, int flags = mpALIGN_NE);

    
    virtual void Rewind() = 0;

    
    virtual bool GetNextXY(double & x, double & y) = 0;

    
    virtual void Plot(wxDC & dc, mpWindow & w);


protected:
    int m_flags; 

	wxCoord maxDrawX, minDrawX, maxDrawY, minDrawY;


    
	void UpdateViewBoundary(wxCoord xnew, wxCoord ynew);

    DECLARE_DYNAMIC_CLASS(mpFXY)
};


class WXDLLIMPEXP_MATHPLOT mpProfile : public mpLayer
{
public:
    
    mpProfile(wxString name = wxEmptyString, int flags = mpALIGN_TOP);

    
    virtual double GetY( double x ) = 0;

    
    virtual void Plot(wxDC & dc, mpWindow & w);

protected:
    int m_flags; 
    DECLARE_DYNAMIC_CLASS(mpProfile)
};








class WXDLLIMPEXP_MATHPLOT mpScaleX : public mpLayer
{
public:
    
    mpScaleX(wxString name = wxT("X"), int flags = mpALIGN_CENTER, bool ticks = true, unsigned int type = mpX_NORMAL);

    
    virtual void Plot(wxDC & dc, mpWindow & w);

    
    virtual bool HasBBox() { return FALSE; }

    
    void SetAlign(int align) { m_flags = align; };

    
    void SetTicks(bool ticks) { m_ticks = ticks; };

    
    bool GetTicks() { return m_ticks; };

    
    unsigned int GetLabelMode() { return m_labelType; };

    
    void SetLabelMode(unsigned int mode) { m_labelType = mode; };
	
	
	void SetLabelFormat(const wxString& format) { m_labelFormat = format; };

	
	const wxString& SetLabelFormat() { return m_labelFormat; };
	
protected:
    int m_flags; //!< Flag for axis alignment
    bool m_ticks; //!< Flag to toggle between ticks or grid
    unsigned int m_labelType; //!< Select labels mode: mpX_NORMAL for normal labels, mpX_TIME for time axis in hours, minutes, seconds
	wxString m_labelFormat; 
    DECLARE_DYNAMIC_CLASS(mpScaleX)
};


class WXDLLIMPEXP_MATHPLOT mpScaleY : public mpLayer
{
public:
    
    mpScaleY(wxString name = wxT("Y"), int flags = mpALIGN_CENTER, bool ticks = true);

    
    virtual void Plot(wxDC & dc, mpWindow & w);

    
    virtual bool HasBBox() { return FALSE; }

    
    void SetAlign(int align) { m_flags = align; };

    
    void SetTicks(bool ticks) { m_ticks = ticks; };

    
    bool GetTicks() { return m_ticks; };
	
	
	void SetLabelFormat(const wxString& format) { m_labelFormat = format; };
	
	
	const wxString& SetLabelFormat() { return m_labelFormat; };

protected:
    int m_flags; //!< Flag for axis alignment
    bool m_ticks; //!< Flag to toggle between ticks or grid
	wxString m_labelFormat; 
    DECLARE_DYNAMIC_CLASS(mpScaleY)
};






#define mpMOUSEMODE_DRAG    0

#define mpMOUSEMODE_ZOOMBOX 1



//WX_DECLARE_HASH_MAP( int, mpLayer*, wxIntegerHash, wxIntegerEqual, wxLayerList );
typedef std::deque<mpLayer*> wxLayerList;


class WXDLLIMPEXP_MATHPLOT mpWindow : public wxWindow
{
public:
    mpWindow() {}
    mpWindow( wxWindow *parent, wxWindowID id,
                     const wxPoint &pos = wxDefaultPosition,
                     const wxSize &size = wxDefaultSize,
                     long flags = 0);
    ~mpWindow();

    
    wxMenu* GetPopupMenu() { return &m_popmenu; }

    
    bool AddLayer( mpLayer* layer, bool refreshDisplay = true);

    
    bool DelLayer( mpLayer* layer, bool alsoDeleteObject = false, bool refreshDisplay = true);

    
    void DelAllLayers( bool alsoDeleteObject, bool refreshDisplay = true);
	
	
    
    mpLayer* GetLayer(int position);

    
    mpLayer* GetLayerByName( const wxString &name);

    
    double GetXscl() { return m_scaleX; }
    double GetScaleX(void) const{ return m_scaleX; }; 
    
    double GetYscl() const { return m_scaleY; }
    double GetScaleY(void) const { return m_scaleY; } 
    
    double GetXpos() const { return m_posX; }
    double GetPosX(void) const { return m_posX; }

    
    double GetYpos() const { return m_posY; }
    double GetPosY(void) const { return m_posY; }

    
    int GetScrX(void) const { return m_scrX; }
    int GetXScreen(void) const { return m_scrX; }

    
    int GetScrY(void) const { return m_scrY; }
    int GetYScreen(void) const { return m_scrY; }

    
    void SetScaleX(double scaleX);

    
    void SetScaleY(double scaleY) { if (scaleY!=0) m_scaleY=scaleY; UpdateAll(); }

    
    void SetPosX(double posX) { m_posX=posX; UpdateAll(); }

    
    void SetPosY(double posY) { m_posY=posY; UpdateAll(); }

    
    void SetPos( double posX, double posY) { m_posX=posX; m_posY=posY; UpdateAll(); }

    
    void SetScr( int scrX, int scrY) { m_scrX=scrX; m_scrY=scrY; }
    
    
//     double p2x(wxCoord pixelCoordX, bool drawOutside = true ); // { return m_posX + pixelCoordX/m_scaleX; }
    inline double p2x(wxCoord pixelCoordX ) { return m_posX + pixelCoordX/m_scaleX; }

    
//     double p2y(wxCoord pixelCoordY, bool drawOutside = true ); //{ return m_posY - pixelCoordY/m_scaleY; }
    inline double p2y(wxCoord pixelCoordY ) { return m_posY - pixelCoordY/m_scaleY; }

    
//     wxCoord x2p(double x, bool drawOutside = true); // { return (wxCoord) ( (x-m_posX) * m_scaleX); }
    inline wxCoord x2p(double x) { return (wxCoord) ( (x-m_posX) * m_scaleX); }

    
//     wxCoord y2p(double y, bool drawOutside = true); // { return (wxCoord) ( (m_posY-y) * m_scaleY); }
    inline wxCoord y2p(double y) { return (wxCoord) ( (m_posY-y) * m_scaleY); }


    
    void EnableDoubleBuffer( bool enabled ) { m_enableDoubleBuffer = enabled; }

    
    void EnableMousePanZoom( bool enabled ) { m_enableMouseNavigation = enabled; }

    
    void LockAspect(bool enable = TRUE);

    
    inline bool IsAspectLocked() { return m_lockaspect; }

    
    void Fit();

    
    void Fit(double xMin, double xMax, double yMin, double yMax,wxCoord *printSizeX=NULL,wxCoord *printSizeY=NULL);

    
    void ZoomIn( const wxPoint& centerPoint = wxDefaultPosition );

    
    void ZoomOut( const wxPoint& centerPoint = wxDefaultPosition );

    
    void ZoomInX();
    
    void ZoomOutX();
    
    void ZoomInY();
    
    void ZoomOutY();

    
    void ZoomRect(wxPoint p0, wxPoint p1);

    
    void UpdateAll();

    
    
    unsigned int CountLayers();
    
    
    unsigned int CountAllLayers() { return m_layers.size(); };

    
    

	
	double GetDesiredXmin() {return m_desiredXmin; }

	
	double GetDesiredXmax() {return m_desiredXmax; }

	
	double GetDesiredYmin() {return m_desiredYmin; }

	
	double GetDesiredYmax() {return m_desiredYmax; }

	
	void GetBoundingBox(double* bbox);
	
    
    void SetMPScrollbars(bool status);

    
    bool GetMPScrollbars() {return m_enableScrollBars; };

    
    bool SaveScreenshot(const wxString& filename, int type = wxBITMAP_TYPE_BMP, wxSize imageSize = wxDefaultSize, bool fit = false);

    
    static double zoomIncrementalFactor;

    
    void SetMargins(int top, int right, int bottom, int left);

    
    void SetMarginTop(int top) { m_marginTop = top; };
    
    void SetMarginRight(int right) { m_marginRight = right; };
    
    void SetMarginBottom(int bottom) { m_marginBottom = bottom; };
    
    void SetMarginLeft(int left) { m_marginLeft = left; };

    
    int GetMarginTop() { return m_marginTop; };
    
    int GetMarginRight() { return m_marginRight; };
    
    int GetMarginBottom() { return m_marginBottom; };
    
    int GetMarginLeft() { return m_marginLeft; };

    
    // void EnableCoordTooltip(bool value = true);
    
    
    
    mpInfoLayer* IsInsideInfoLayer(wxPoint& point);
	
	
	void SetLayerVisible(const wxString &name, bool viewable);
	
	
	bool IsLayerVisible(const wxString &name );
	
	
	void SetLayerVisible(const unsigned int position, bool viewable);
	
	
	bool IsLayerVisible(const unsigned int position );

	
	void SetColourTheme(const wxColour& bgColour, const wxColour& drawColour, const wxColour& axesColour);
	
	
	const wxColour& GetAxesColour() { return m_axColour; };

protected:
    void OnPaint         (wxPaintEvent     &event); //!< Paint handler, will plot all attached layers
    void OnSize          (wxSizeEvent      &event); //!< Size handler, will update scroll bar sizes
    // void OnScroll2       (wxScrollWinEvent &event); //!< Scroll handler, will move canvas
    void OnShowPopupMenu (wxMouseEvent     &event); //!< Mouse handler, will show context menu
    void OnMouseRightDown(wxMouseEvent     &event); //!< Mouse handler, for detecting when the user drags with the right button or just "clicks" for the menu
    void OnCenter        (wxCommandEvent   &event); //!< Context menu handler
    void OnFit           (wxCommandEvent   &event); //!< Context menu handler
    void OnZoomIn        (wxCommandEvent   &event); //!< Context menu handler
    void OnZoomOut       (wxCommandEvent   &event); //!< Context menu handler
    void OnLockAspect    (wxCommandEvent   &event); //!< Context menu handler
    void OnMouseHelp     (wxCommandEvent   &event); //!< Context menu handler
    void OnMouseWheel    (wxMouseEvent     &event); //!< Mouse handler for the wheel
    void OnMouseMove     (wxMouseEvent     &event); //!< Mouse handler for mouse motion (for pan)
    void OnMouseLeftDown (wxMouseEvent     &event); //!< Mouse left click (for rect zoom)
    void OnMouseLeftRelease (wxMouseEvent  &event); //!< Mouse left click (for rect zoom)
    void OnScrollThumbTrack (wxScrollWinEvent &event); //!< Scroll thumb on scroll bar moving
    void OnScrollPageUp     (wxScrollWinEvent &event); //!< Scroll page up 
    void OnScrollPageDown   (wxScrollWinEvent &event); //!< Scroll page down 
    void OnScrollLineUp     (wxScrollWinEvent &event); //!< Scroll line up 
    void OnScrollLineDown   (wxScrollWinEvent &event); //!< Scroll line down
    void OnScrollTop        (wxScrollWinEvent &event); //!< Scroll to top 
    void OnScrollBottom     (wxScrollWinEvent &event); 
    void DoScrollCalc    (const int position, const int orientation);

    void DoZoomInXCalc   (const int         staticXpixel);
    void DoZoomInYCalc   (const int         staticYpixel);
    void DoZoomOutXCalc  (const int         staticXpixel);
    void DoZoomOutYCalc  (const int         staticYpixel);

    
    virtual bool UpdateBBox();

    //wxList m_layers;    //!< List of attached plot layers
    wxLayerList m_layers; //!< List of attached plot layers
    wxMenu m_popmenu;   //!< Canvas' context menu
    bool   m_lockaspect;//!< Scale aspect is locked or not
    // bool   m_coordTooltip; //!< Selects whether to show coordinate tooltip
	wxColour m_bgColour;
	wxColour m_fgColour;
	wxColour m_axColour;

    double m_minX;      //!< Global layer bounding box, left border incl.
    double m_maxX;      //!< Global layer bounding box, right border incl.
    double m_minY;      //!< Global layer bounding box, bottom border incl.
    double m_maxY;      //!< Global layer bounding box, top border incl.
    double m_scaleX;    //!< Current view's X scale
    double m_scaleY;    //!< Current view's Y scale
    double m_posX;      //!< Current view's X position
    double m_posY;      //!< Current view's Y position
    int    m_scrX;      //!< Current view's X dimension
    int    m_scrY;      //!< Current view's Y dimension
    int    m_clickedX;  //!< Last mouse click X position, for centering and zooming the view
    int    m_clickedY;  
    
    double m_desiredXmin,m_desiredXmax,m_desiredYmin,m_desiredYmax;

    int m_marginTop, m_marginRight, m_marginBottom, m_marginLeft;

    int         m_last_lx,m_last_ly;   //!< For double buffering
    wxMemoryDC  m_buff_dc;             //!< For double buffering
    wxBitmap    *m_buff_bmp;            //!< For double buffering
    bool        m_enableDoubleBuffer;  //!< For double buffering
    bool        m_enableMouseNavigation;  //!< For pan/zoom with the mouse.
    bool        m_mouseMovedAfterRightClick;
    long        m_mouseRClick_X,m_mouseRClick_Y; //!< For the right button "drag" feature
    int         m_mouseLClick_X, m_mouseLClick_Y; //!< Starting coords for rectangular zoom selection
    bool        m_enableScrollBars;
    int         m_scrollX, m_scrollY;
    mpInfoLayer* m_movingInfoLayer;      
    DECLARE_DYNAMIC_CLASS(mpWindow)
    DECLARE_EVENT_TABLE()
};




class WXDLLIMPEXP_MATHPLOT mpFXYVector : public mpFXY
{
public:
    
    mpFXYVector(wxString name = wxEmptyString, int flags = mpALIGN_NE);

    
    void SetData( const std::vector<double> &xs,const std::vector<double> &ys);

    
    void Clear();

protected:
    
    std::vector<double>  m_xs,m_ys;

    
    size_t              m_index;

    
    double              m_minX,m_maxX,m_minY,m_maxY;

    
    void Rewind();

    
    bool GetNextXY(double & x, double & y);

    
    double GetMinX() { return m_minX; }

    
    double GetMinY() { return m_minY; }

    
    double GetMaxX() { return m_maxX; }

    
    double GetMaxY() { return m_maxY; }

    int     m_flags; 
    DECLARE_DYNAMIC_CLASS(mpFXYVector)
};




class WXDLLIMPEXP_MATHPLOT mpText : public mpLayer
{
public:
    
    mpText(wxString name = wxT("Title"), int offsetx = 5, int offsety = 50);

    
    virtual void Plot(wxDC & dc, mpWindow & w);

    
    virtual bool HasBBox() { return FALSE; }

protected:
    int m_offsetx; //!< Holds offset for X in percentage
    int m_offsety; 
    DECLARE_DYNAMIC_CLASS(mpText)
};





class WXDLLIMPEXP_MATHPLOT mpMarker : public mpLayer
{
public:
    
    mpMarker(wxString name = wxT("[M]"), double atX = 0.0, double atY = 0.0);
    
    
    void SetPos(double atX, double atY) {mX = atX, mY = atY; };

    
    virtual void Plot(wxDC & dc, mpWindow & w);

    
    virtual bool HasBBox() { return FALSE; }

protected:

    double  mX, mY;

    DECLARE_DYNAMIC_CLASS(mpText)
};





class WXDLLIMPEXP_MATHPLOT mpPrintout : public wxPrintout
{
public:
    mpPrintout(mpWindow* drawWindow, const wxChar *title = _T("wxMathPlot print output"));
    virtual ~mpPrintout() {};

    void SetDrawState(bool drawState) {drawn = drawState;};
    bool OnPrintPage(int page);
    bool HasPage(int page);

private:
    bool drawn;
    mpWindow *plotWindow;
};




class WXDLLIMPEXP_MATHPLOT mpMovableObject : public mpLayer
{
public:
    
    mpMovableObject( ) :
        m_reference_x(0),
        m_reference_y(0),
        m_reference_phi(0),
        m_shape_xs(0),
        m_shape_ys(0)
    {
        m_type = mpLAYER_PLOT;
    }

    virtual ~mpMovableObject() {};

    
    void GetCoordinateBase( double &x, double &y, double &phi ) const
    {
        x = m_reference_x;
        y = m_reference_y;
        phi = m_reference_phi;
    }

    
    void SetCoordinateBase( double x, double y, double phi = 0 )
    {
        m_reference_x = x;
        m_reference_y = y;
        m_reference_phi = phi;
        m_flags  = mpALIGN_NE;
        ShapeUpdated();
    }

    virtual bool HasBBox() { return m_trans_shape_xs.size()!=0; }

    
    virtual double GetMinX() { return m_bbox_min_x; }

    
    virtual double GetMaxX() { return  m_bbox_max_x; }

    
    virtual double GetMinY() { return m_bbox_min_y; }

    
    virtual double GetMaxY() { return m_bbox_max_y; }

    virtual void   Plot(wxDC & dc, mpWindow & w);

    
    void SetAlign(int align) { m_flags = align; };

protected:
    int m_flags; 
    
    double m_reference_x,m_reference_y,m_reference_phi;

    
    void TranslatePoint( double x,double y, double &out_x, double &out_y );

    
    std::vector<double>  m_shape_xs,m_shape_ys;

    
    std::vector<double>  m_trans_shape_xs,m_trans_shape_ys;

    
    double  m_bbox_min_x,m_bbox_max_x,m_bbox_min_y,m_bbox_max_y;

    
    void ShapeUpdated();

};



class WXDLLIMPEXP_MATHPLOT mpCovarianceEllipse : public mpMovableObject
{
public:
    
    mpCovarianceEllipse(
        double cov_00 = 1,
        double cov_11 = 1,
        double cov_01 = 0,
        double quantiles = 2,
        int    segments = 32,
        const wxString & layerName = wxT("") ) :
            m_cov_00(cov_00),
            m_cov_11(cov_11),
            m_cov_01(cov_01),
            m_quantiles(quantiles),
            m_segments(segments)
    {
        m_continuous = true;
        m_name = layerName;
        RecalculateShape();
        m_type = mpLAYER_PLOT;
    }

    virtual ~mpCovarianceEllipse() {}

    double GetQuantiles() const { return m_quantiles; }

    
    void SetQuantiles(double q)
    {
        m_quantiles=q;
        RecalculateShape();
    }

    void SetSegments( int segments ) { m_segments = segments; }
    int GetSegments( ) const { return m_segments; }

    
    void GetCovarianceMatrix( double &cov_00,double &cov_01,double &cov_11 ) const
    {
        cov_00 = m_cov_00;
        cov_01 = m_cov_01;
        cov_11 = m_cov_11;
    }

    
    void SetCovarianceMatrix( double cov_00,double cov_01,double cov_11 )
    {
        m_cov_00 = cov_00;
        m_cov_01 = cov_01;
        m_cov_11 = cov_11;
        RecalculateShape();
    }

protected:
    
    double m_cov_00,m_cov_11,m_cov_01;
    double m_quantiles;

    
    int m_segments;

    
    void RecalculateShape();
};



class WXDLLIMPEXP_MATHPLOT mpPolygon : public mpMovableObject
{
public:
    
    mpPolygon( const wxString & layerName = wxT("") )
    {
        m_continuous = true;
        m_name = layerName;
    }

    virtual ~mpPolygon() {}

    
    void setPoints(
        const std::vector<double>&  points_xs,
        const std::vector<double>&  points_ys,
        bool                   closedShape=true );



};



class WXDLLIMPEXP_MATHPLOT mpBitmapLayer : public mpLayer
{
public:
    
    mpBitmapLayer( )
    {
        m_min_x = m_max_x =
        m_min_y = m_max_y = 0;
        m_validImg = false;
        m_type = mpLAYER_BITMAP;
    }

    virtual ~mpBitmapLayer() {};

    
    void GetBitmapCopy( wxImage &outBmp ) const;

    
    void SetBitmap( const wxImage &inBmp, double x, double y, double lx, double ly );

    virtual bool HasBBox() { return true; }

    
    virtual double GetMinX() { return m_min_x; }

    
    virtual double GetMaxX() { return  m_max_x; }

    
    virtual double GetMinY() { return m_min_y; }

    
    virtual double GetMaxY() { return m_max_y; }

    virtual void   Plot(wxDC & dc, mpWindow & w);

    
    void SetAlign(int align) { m_flags = align; };

protected:
    int m_flags; 
    
    wxImage      m_bitmap;
    wxBitmap     m_scaledBitmap;
    wxCoord      m_scaledBitmap_offset_x,m_scaledBitmap_offset_y;


    bool            m_validImg;


    
    double  m_min_x,m_max_x,m_min_y,m_max_y;


};





#endif // _MP_MATHPLOT_H_
